grammar CMM;

program:
           statement*;
statement:
             expr_stat
         |
             arr_decl_stat
         |
             decl_stat
         |
             assign_stat
         |
             if_stat
         |
             while_stat
         |
             break_stat
         |
             read_stat
         |
             write_stat
         ;
expr_stat:
             expr';';
decl_stat:
             TYPE ID('='expr)?(','ID('='expr)?)*';'
         ;
arr_decl_stat:
                 TYPE ('['INT']' ID | ID '['INT']') ';';

assign_stat:
               identifier '=' expr ';'
           ;
identifier:
              ID
          |
              ID'['expr']';
if_stat:
           IF'('expr')'block(ELSE block)?;
block:
         '{'statement*'}';
while_stat:
              WHILE'('expr')'block;
break_stat:
              BREAK ';';
read_stat:
             READ'('identifier')'';';
write_stat:
              WRITE'(' expr')'';';
expr:
        cal_expr(('<'|'<='|'>'|'>='|'=='|'!=')cal_expr)?;
cal_expr:
            mul_expr(('+'|'-')mul_expr)*;
mul_expr:
           ('+'|'-')?atom(('*'|'/')('+'|'-')?atom)*;
atom:
        INT
    |
        HEXINT
    |
        DOUBLE
    |
        identifier
    |
        '('expr')';
READ:
        'read';
WRITE:
         'write';
WHILE:
         'while';
BREAK:
         'break';
IF:
      'if';
ELSE:
        'else';
TYPE:
        'double'|'int';
ID  :     LETTER
        |
        (LETTER | '_')   (LETTER | [0-9]|'_')* (LETTER | [0-9]) ;
fragment
LETTER : [a-zA-Z] ;

INT :   [1-9][0-9]* | '0';
DOUBLE:   INT '.' [0-9]*;
HEXINT:  '0' [x|X] [0-9a-fA-F]+ ;

WS  :   [ \t\n\r]+ -> skip ;

SL_COMMENT
    :   '//' .*? '\n' -> skip
    ;
MUL_COMMENT
    :   '/*' .*? '*/' ->skip
    ;
